package com.apache.rpc.service.impl;

import com.apache.api.vo.ParamsVo;
import com.apache.cache.service.CacheManager;
import com.apache.cache.service.impl.LoadCacheFactory;
import com.apache.cache.util.Validator;
import com.apache.database.db.IDao;
import com.apache.database.model.MethodParam;
import com.apache.database.model.Page;
import com.apache.database.model.TaskEntity;
import com.apache.exception.BusinessException;
import com.apache.rpc.manager.DynamicDatabaseManager;
import com.apache.tools.DataMap;
import com.apache.tools.StrUtil;
import org.apache.log4j.Logger;

import java.util.List;

/**
 * description: 定时任务管理manager
 *
 * @author dyh 创建时间：2018年10月01日
 * CREATE TABLE t_task_timer (
    task_key  varchar(60) NOT NULL ,
    class_name  varchar(255) NOT NULL ,
    method_name  varchar(255) NULL DEFAULT 'run' ,
    task_type  varchar(255) NULL ,
    interval_type  bigint NULL DEFAULT '0' ,
    hour  bigint NULL DEFAULT '0' ,
    minute  bigint NULL DEFAULT '0' ,
    second  bigint NULL DEFAULT '0' ,
    description  varchar(300) NULL ,
    start_time  int NULL DEFAULT '0' ,
    end_time  int NULL DEFAULT '0' ,
    task_status  int NULL DEFAULT '0' ,
    sys_name  varchar(255) NULL ,
    server_ip  varchar(255) NULL ,
    create_time datetime NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (task_key),
    INDEX task_timer_sys_name_index (sys_name) USING BTREE ,
    INDEX task_timer_sys_ip_index (server_ip) USING BTREE ,
    INDEX task_timer_class_name_index (class_name) USING BTREE
   );
 */
public class TaskTimerManagerImpl implements DynamicDatabaseManager {

    private final String entityName="com.apache.rpc.entity.DynamicDatabase";
    private final String cloumnStr="task_key,class_name,method_name,task_type,interval_type,hour,minute,second,description,start_time,end_time,task_status,sys_name,server_ip";
    private final String tableName="t_task_timer";
    protected Logger log = Logger.getLogger(getClass());
    private IDao dynamicDatabaseDao;
    private CacheManager cache;

    public void setDynamicDatabaseDao(IDao dynamicDatabaseDao) {
        this.dynamicDatabaseDao = dynamicDatabaseDao;
    }

    @Override
    public String saveInfo(ParamsVo vo) throws BusinessException {
        TaskEntity entity = (TaskEntity)vo.getObj();
        if(Validator.isNull(entity.getTaskKey())){
            entity.setTaskKey(Validator.generate());
        }
        StringBuilder sb = new StringBuilder("insert into "+tableName+" (");
        sb.append(cloumnStr+")");
        sb.append(" values(");
        sb.append("'"+entity.getTaskKey()+"',");
        sb.append("'"+entity.getClassName()+"',");
        sb.append("'"+ StrUtil.doNull(entity.getMethodName(),"run")+"',");
        sb.append("'"+ StrUtil.doNull(entity.getTaskType(),"")+"',");
        sb.append(Long.valueOf(StrUtil.doNull(String.valueOf(entity.getIntervalType()),"0"))+",");
        sb.append(Long.valueOf(StrUtil.doNull(String.valueOf(entity.getHour()),"0"))+",");//小时
        sb.append(Long.valueOf(StrUtil.doNull(String.valueOf(entity.getMinute()),"0"))+",");//分钏
        sb.append(Long.valueOf(StrUtil.doNull(String.valueOf(entity.getSecond()),"0"))+",");//秒
        sb.append("'"+ StrUtil.doNull(entity.getDescription(),"")+"',");//描述
        sb.append(Integer.valueOf(StrUtil.doNull(String.valueOf(entity.getStartTime()),"0"))+",");//开始时点(0~23)
        sb.append(Integer.valueOf(StrUtil.doNull(String.valueOf(entity.getEndTime()),"0"))+",");//结束时点(0~23)
        sb.append(Integer.valueOf(StrUtil.doNull(String.valueOf(entity.getTaskStatus()),"0"))+",");//状态;
        sb.append("'"+ StrUtil.doNull(entity.getSysName(),"")+"',");
        sb.append("'"+ StrUtil.doNull(entity.getServerIp(),"")+"'");
        sb.append(")");
        MethodParam param = new MethodParam("DynamicDatabase", "", "", entityName);
        param.setParams("dyncSql",sb.toString());
        boolean mark = dynamicDatabaseDao.edit(param);
        if(mark){
            getCache().createCacheObject(entity.getTaskKey(),entity);
            return entity.getTaskKey();
        }else {
            return "";
        }
    }

    @Override
    public boolean editInfo(ParamsVo vo) throws BusinessException {
        TaskEntity entity = (TaskEntity)vo.getObj();
        if(Validator.isNull(entity.getTaskKey())){
            return false;
        }
        StringBuilder sb = new StringBuilder("UPDATE "+tableName+" set ");
        sb.append("class_name='"+entity.getClassName()+"'");
        if(Validator.isNotNull(entity.getMethodName())) {
            sb.append(",method_name='" + entity.getMethodName() + "'");
        }
        if(Validator.isNotNull(entity.getTaskType())) {
            sb.append(",task_type='" + entity.getTaskType() + "'");
        }
        if(Validator.isNotNull(entity.getDescription())) {
            sb.append(",description='" + entity.getDescription() + "'");
        }
        if(Validator.isNotNull(entity.getSysName())) {
            sb.append(",sys_name='" + entity.getSysName() + "'");
        }
        if(Validator.isNotNull(entity.getServerIp())) {
            sb.append(",server_ip='" + entity.getServerIp() + "'");
        }
        sb.append(",interval_type="+StrUtil.doNull(String.valueOf(entity.getIntervalType()),"0"));
        sb.append(",hour="+StrUtil.doNull(String.valueOf(entity.getHour()),"0"));//小时
        sb.append(",minute="+StrUtil.doNull(String.valueOf(entity.getMinute()),"0"));//分钏
        sb.append(",second="+StrUtil.doNull(String.valueOf(entity.getSecond()),"0"));//秒
        sb.append(",start_time="+StrUtil.doNull(String.valueOf(entity.getStartTime()),"0"));//开始时点(0~23)
        sb.append(",end_time="+StrUtil.doNull(String.valueOf(entity.getEndTime()),"0"));//结束时点(0~23)
        sb.append(",task_status="+StrUtil.doNull(String.valueOf(entity.getTaskStatus()),"0"));//状态;
        sb.append(" where task_key='"+entity.getTaskKey()+"'");
        MethodParam param = new MethodParam("DynamicDatabase", "", "", entityName);
        param.setParams("dyncSql",sb.toString());
        boolean mark = dynamicDatabaseDao.edit(param);
        if(mark){
            Object obj = getCache().getCacheObjectByKey(entity.getTaskKey());
            if(null !=obj){
                TaskEntity task = (TaskEntity)obj;
                entity.setOpenStart(task.isOpenStart());
            }
            getCache().createCacheObject(entity.getTaskKey(),entity);
        }
        return mark;
    }

    @Override
    public boolean deleteInfo(ParamsVo paramsVo) throws BusinessException {
        if(Validator.isNull(paramsVo.getInfoId())){
            return false;
        }
        MethodParam param = new MethodParam("DynamicDatabase", "", "", entityName);
        param.setDelete(true);
        param.setParams("dyncSql","delete from "+tableName+" where task_key='"+paramsVo.getInfoId()+"'");
        boolean mark = dynamicDatabaseDao.delete(param);
        if(mark){
            getCache().removeCacheObject(paramsVo.getInfoId());
        }
        return mark;
    }

    @Override
    public Object execute(ParamsVo vo) {
        String key = vo.getKey();
        if("initCache".equalsIgnoreCase(key)){//初始化缓存
            initCache(vo.getParamsToStr("sysName"));
        }else if("findIds".equalsIgnoreCase(key)){
            vo.setMethodKey("ForIds");
            return findIds(vo);
        }
        return null;
    }

    private void initCache(String sysName){
        MethodParam param = new MethodParam("ByObjInfo", "", "", entityName);
        StringBuilder sb = new StringBuilder("select "+cloumnStr+" from "+tableName);
        if(Validator.isNotNull(sysName)){
            sb.append(" where sys_name='"+sysName+"'");
        }
        param.setParams("dyncSql",sb.toString());
        List<DataMap> list = dynamicDatabaseDao.select(param);
        if(Validator.isEmpty(list))
            return ;
        for(DataMap map : list){
            TaskEntity task = new TaskEntity(map);
            getCache().createCacheObject(task.getTaskKey(),task);
        }
        log.info("初始化[定时任务信息]到缓存完成！");
    }

    private List<String> findIds(ParamsVo vo){
        MethodParam param =setMethodParams(vo);
        int pageSize = Integer.valueOf(Validator.getDefaultStr(String.valueOf(vo.getParams("pageSize")), "0"));
        if(pageSize==0){
            return dynamicDatabaseDao.select(param);
        }else{
            StringBuilder sb = new StringBuilder("select ");
            sb.append("task_key");
            sb.append(" from "+tableName+" where 1=1 ");
            if(Validator.isNotNull(vo.getParamsToStr("sysName"))){
                sb.append(" and sys_name='"+vo.getParamsToStr("sysName")+"'");
            }
            if(Validator.isNotNull(vo.getParamsToStr("serverIp"))){
                sb.append(" and server_ip='"+vo.getParamsToStr("serverIp")+"'");
            }
            sb.append(" order by create_time desc");
            int pageIndex = Integer.valueOf(Validator.getDefaultStr(String.valueOf(vo.getParams("pageIndex")), "1"));
            param.setPageIndex(pageIndex);
            param.setPageSize(pageSize);
            Page page = dynamicDatabaseDao.pageSelect(param);
            return page.getPageObjects();
        }
    }

    @Override
    public Object getInfoById(ParamsVo paramsVo) {
        if(Validator.isNull(paramsVo.getInfoId())){
            return null;
        }
        Object obj = getCache().getCacheObjectByKey(paramsVo.getInfoId());
        if(null == obj) {
            MethodParam param = setMethodParams(paramsVo);
            param.setParams("dyncSql",
                    param.getParamsByKey("dyncSql") + " and task_key='" + paramsVo.getInfoId() + "'");
            Object object = dynamicDatabaseDao.selectSingle(param);
            if(null == object){
                return null;
            }
            TaskEntity task = new TaskEntity((DataMap)object);
            getCache().createCacheObject(task.getTaskKey(),task);
            return task;
        }
        return obj;
    }

    @Override
    public List getList(ParamsVo paramsVo) {
        MethodParam param = setMethodParams(paramsVo);
        param.setOrderby(" create_time desc");
        return dynamicDatabaseDao.select(param);
    }

    @Override
    public long countInfo(ParamsVo paramsVo) {
        return dynamicDatabaseDao.count(setMethodParams(paramsVo));
    }


    @Override
    public Page getPageInfo(ParamsVo vo) {
        MethodParam param = setMethodParams(vo);
        param.setOrderby(" create_time desc");
        int pageSize = Integer
                .valueOf(Validator.getDefaultStr(String.valueOf(vo.getParams("pageSize")), "10"));
        int pageIndex = Integer
                .valueOf(Validator.getDefaultStr(String.valueOf(vo.getParams("pageIndex")), "1"));
        param.setPageIndex(pageIndex);
        param.setPageSize(pageSize);
        return dynamicDatabaseDao.pageSelect(param);
    }

    private MethodParam setMethodParams(ParamsVo vo) {
        String methodKey = Validator.getDefaultStr(vo.getMethodKey(), "ByObjInfo");
        MethodParam param = new MethodParam(methodKey, "", "", entityName);
        param.setResultCache(false);
        if(Validator.isNotNull(vo.getParamsToStr("dyncSql"))){
            param.setParams("dyncSql",vo.getParamsToStr("dyncSql"));
            return param;
        }
        StringBuilder sb = new StringBuilder("select ");
        sb.append(cloumnStr+",create_time");
        sb.append(" from "+tableName+" where 1=1 ");
        if(Validator.isNotNull(vo.getParamsToStr("taskKey"))){
            sb.append(" and task_key='"+vo.getParamsToStr("taskKey")+"'");
        }
        if(Validator.isNotNull(vo.getParamsToStr("sysName"))){
            sb.append(" and sys_name='"+vo.getParamsToStr("sysName")+"'");
        }
        if(Validator.isNotNull(vo.getParamsToStr("serverIp"))){
            sb.append(" and server_ip='"+vo.getParamsToStr("serverIp")+"'");
        }
        if(Validator.isNotNull(vo.getParamsToStr("className"))){
            sb.append(" and class_name='"+vo.getParamsToStr("className")+"'");
        }
        if(Validator.isNotNull(vo.getParamsToStr("methodName"))){
            sb.append(" and method_name='"+vo.getParamsToStr("methodName")+"'");
        }
        param.setParams("dyncSql",sb.toString());
        return param;
    }

    private CacheManager getCache(){
        if(null==cache){
            cache = LoadCacheFactory.getInstance().getCacheManager("task_timer_map");
        }
       return cache;
    }
}
